#include "../clibs/hash_container.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>

void mfree(void *ptr, size_t size) {}

uint64_t hhh(void *v) { return *((uint64_t *)v); }

int cmp(void *a, void *b) {
  if (!a || !b)
    return 1;
  uint64_t aa = *((uint64_t *)a);
  uint64_t bb = *((uint64_t *)b);
  if (aa < bb) {
    return 1;
  } else if (aa == bb) {
    return 0;
  }
  return -1;
}

int on_value(void *v) {
  printf("%lu\n", *((uint64_t *)v));
  return 0;
}

void test_hash_tree() {
  hash_table_tree_t *tree =
      create_hash_table_tree(malloc, mfree, hhh, cmp, 100);
  uint64_t a = 232, b = 2, c = 3, d = 4;
  void *pre = NULL;
  hash_table_tree_set(tree, (void *)&a, &pre);
  hash_table_tree_set(tree, (void *)&b, &pre);
  hash_table_tree_set(tree, (void *)&c, &pre);
  hash_table_tree_set(tree, (void *)&d, &pre);
  void *v = hash_table_tree_get(tree, (void *)&c);
  printf("v = %lu\n", *((uint64_t *)v));
  hash_table_tree_pop(tree, (void *)&c);
  // hash_tree_foreach(tree, on_value);
  // printf("===================================\n");
  // hash_tree_pop(tree, (void *)&b);
  hash_table_tree_foreach(tree, on_value);
  // v = hash_tree_get(tree, (void *)&a);
  // if (v) {
  //   printf("%lu\n", *((uint64_t *)v));
  // }
  // v = hash_tree_get(tree, (void *)&b);
  // if (v) {
  //   printf("%lu\n", *((uint64_t *)v));
  // }
  // v = hash_tree_get(tree, (void *)&d);
  // if (v) {
  //   printf("%lu\n", *((uint64_t *)v));
  // }
  // hash_tree_foreach(tree, on_value);
  destroy_hash_table_tree(tree);
}

#include <map>
#include <time.h>
#include <unordered_set>

#define count_ 100000
void test_hash_speed() {
  hash_table_tree_t *tree =
      create_hash_table_tree(malloc, mfree, hhh, cmp, count_);
  int a[count_] = {0};
  for (int i = 0; i < count_; ++i)
    a[i] = i;

  std::unordered_set<int> sss;
  std::map<int, int> sssm;

  clock_t pre = clock();
  void *ppp;
  for (int i = 0; i < count_; ++i)
    hash_table_tree_set(tree, a + i, &ppp);
  for (int i = 0; i < count_; ++i)
    hash_table_tree_get(tree, a + i);
  printf("hash tree use = %lu\n", clock() - pre);

  pre = clock();
  for (int i = 0; i < count_; ++i)
    sss.insert(a[i]);
  for (int i = 0; i < count_; ++i)
    sss.find(a[i]);
  printf("set use = %lu\n", clock() - pre);

  pre = clock();
  for (int i = 0; i < count_; ++i)
    sssm[a[i]] = i;
  for (int i = 0; i < count_; ++i)
    sssm.find(a[i]);
  printf("map use = %lu\n", clock() - pre);
}

int main(int argc, char **argv) {
  test_hash_tree();
  test_hash_speed();
}